package com.weitu.workflow.flowManagement.service.impl;

import com.weitu.util.IDGenerator;
import com.weitu.workflow.definition.constant.FlowDefConstants;
import com.weitu.workflow.flowManagement.entity.WorkItemInfo;
import com.weitu.workflow.flowManagement.entity.WorkflowInstance;
import com.weitu.workflow.flowManagement.entity.WorkflowReview;
import com.weitu.workflow.flowManagement.entity.WorkflowTaskInstance;
import com.weitu.workflow.flowManagement.mapper.FlowManagementMapper;
import com.weitu.workflow.flowManagement.service.FlowManagementService;
import org.apache.log4j.Logger;
import org.fireflow.engine.EngineException;
import org.fireflow.engine.IProcessInstance;
import org.fireflow.engine.IWorkItem;
import org.fireflow.engine.RuntimeContext;
import org.fireflow.engine.definition.WorkflowDefinition;
import org.fireflow.engine.definition.WorkflowDefinitionInfo;
import org.fireflow.engine.impl.ProcessInstance;
import org.fireflow.engine.impl.WorkItem;
import org.fireflow.kernel.KernelException;
import org.fireflow.model.FormTask;
import org.fireflow.model.Task;
import org.fireflow.model.net.*;
import org.fireflow.model.resource.Form;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Administrator on 2017/3/17.
 */
@Service
public class FlowManagementServiceImpl implements FlowManagementService {
    @Autowired
    private FlowManagementMapper flowManagementMapper;//流程管理mapper
    @Autowired
    private RuntimeContext runtimeContext;
    private Logger log=Logger.getLogger(this.getClass());

    /***
     * 启动工作流实例并运行
     * @param businessIdentity
     * @param actorId
     * @return
     */
    public IProcessInstance flowCreateAndRun(String businessIdentity,String businessId,String businessContent, String actorId) throws Exception {
        Map<String,String> dataMap=new HashMap<String, String>();
        return this.flowCreateAndRun(businessIdentity,businessId,businessContent,actorId,dataMap);

    }
    /***
     * 启动工作流实例并运行
     * @param businessIdentity 业务标识
     * @param businessId 业务id
     * @param actorId 创建人
     * @param dataMap  流程变量
     * @return IProcessInstance
     */
    @Transactional
    public IProcessInstance flowCreateAndRun(String businessIdentity,String businessId,String businessContent,String actorId,Map<String,String> dataMap) throws Exception{
        //查询业务关联的流程实例
        WorkflowInstance workflowInstance=this.queryWorkflowInstanceByBusinessId(businessId);
        if (workflowInstance!=null&&workflowInstance.getState()>=0){
            log.error(new Exception("业务["+businessId+"]流程已经存在，无法重复创建！"));
            return null;
        }
        //根据业务标识查询流程信息
        WorkflowDefinitionInfo workflowDefinitionInfo=this.flowManagementMapper.queryWorkflowDefinitionInfoByBusinessIdentity(businessIdentity);
        if(workflowDefinitionInfo==null){
            log.error(new Exception("业务["+businessIdentity+"]无关联流程！"));
            return null;
        }
        //创建流程实例
        IProcessInstance processInstance = this.runtimeContext.getWorkflowSession().createProcessInstance(workflowDefinitionInfo.getProcessId(), actorId);
        //设置流程实例变量
        processInstance.setProcessInstanceVariable(FlowDefConstants.FLOW_BIZ_ID, businessId);//流程实例关联的业务id
        if(dataMap!=null){
            for(String key:dataMap.keySet()){
                processInstance.setProcessInstanceVariable(key, dataMap.get(key));
            }
        }

        //保存流程实例
        this.runtimeContext.getPersistenceService().saveOrUpdateProcessInstance(processInstance);
        //保存业务描述信息
        if(businessContent!=null){
            this.saveOrUpdateBusinessContent(processInstance.getId(),businessContent);
        }
        //启动流程实例
        processInstance.run();
        return processInstance;
    }
    /***
     * 根据业务id查询业务流程实例信息
     * @param businessId
     * @return
     */
    public WorkflowInstance queryWorkflowInstanceByBusinessId(String businessId){
        return this.flowManagementMapper.queryWorkflowInstanceByBusinessId(businessId);
    }
    /***
     * 根据业务id查询业务流程实例
     * @param workItemId
     * @return
     */
    public WorkflowInstance queryWorkflowInstanceByWorkItemId(String workItemId){
        return this.flowManagementMapper.queryWorkflowInstanceByWorkItemId(workItemId);
    }
    /***
     * 根据流程实例id查询任务实例集合
     * @param workflowInstanceId
     * @return List<WorkflowTaskInstance>
     */
    public List<WorkflowTaskInstance> queryTaskInstanceListByWorkflowId(String workflowInstanceId){
        return this.flowManagementMapper.queryTaskInstanceListByWorkflowId(workflowInstanceId);
    }
    /***
     * 根据任务实例id查询工作项集合
     * @param workflowTaskInstanceId
     * @return List<WorkItemInfo>
     */
    public List<WorkItemInfo> queryWorkItemInfoListByTaskInstanceId(String workflowTaskInstanceId){
        return this.flowManagementMapper.queryWorkItemInfoListByTaskInstanceId(workflowTaskInstanceId);
    }
    /***
     * 根据业务标识查询流程定义信息
     * @param businessIdentity
     * @return
     */
    public WorkflowDefinitionInfo queryWorkflowDefinitionInfoByBusinessIdentity(String businessIdentity){
        return this.flowManagementMapper.queryWorkflowDefinitionInfoByBusinessIdentity(businessIdentity);
    }
    /***
     * 根据流程实例id保存业务内容
     * @param processInstanceId
     */
    public void saveOrUpdateBusinessContent(String processInstanceId,String businessContent){
        String oldBusinessContent=this.flowManagementMapper.queryBusinessContentByProcessInstanceId(processInstanceId);
        if (oldBusinessContent==null){
            this.flowManagementMapper.insetProcessInstanceBusinessContent(processInstanceId,businessContent);
        }else{
            this.flowManagementMapper.updateProcessInstanceBusinessContent(processInstanceId,businessContent);
        }
    }
    /***
     * 根据用户名查询工作数量
     * @param paramMap
     * @return
     */
    public int queryWorkItemCount(Map<String,Object> paramMap){
        return  this.flowManagementMapper.queryWorkItemCount(paramMap);
    }
    /***
     * 根据用户名查询工作事项
     * @param paramMap
     * @return
     */
    public List<WorkItemInfo> queryWorkItemList(Map<String,Object> paramMap){
        return this.flowManagementMapper.queryWorkItemList(paramMap);
    }
    /***
     * 根据工作项id查询工作项信息
     * @param workItemId
     * @return
     */
    public WorkItemInfo queryWorkItemInfoByWorkItemId(String workItemId){
        WorkItemInfo workItemInfo=this.flowManagementMapper.queryWorkItemInfoByWorkItemId(workItemId);
        if (workItemInfo!=null){
            IProcessInstance processInstance= this.runtimeContext.getPersistenceService().findProcessInstanceById(workItemInfo.getProcessInstanceId());
            Object flowBizId=processInstance.getProcessInstanceVariable(FlowDefConstants.FLOW_BIZ_ID);
            workItemInfo.setBusinessId(flowBizId!=null?flowBizId.toString():"");
        }
        return workItemInfo;
    }
    /***
     * 根据工作项id查询业务表单地址
     * @param workItemId
     * @param formType 0：只读表单；1：编辑表单
     * @return
     */
    public String queryBusinessFormByWorkItemId(String workItemId,int formType){
        WorkItemInfo workItemInfo=this.flowManagementMapper.queryWorkItemInfoByWorkItemId(workItemId);
        //查询流程定义信息
        WorkflowDefinition workflowDefinition=this.runtimeContext.getPersistenceService().findWorkflowDefinitionByProcessIdAndVersionNumber(workItemInfo.getProcessId(),workItemInfo.getVersion());
        List<Activity> activities=workflowDefinition.getWorkflowProcess().getActivities();
        for (Activity activity:activities){
            if (activity.getId().equals(workItemInfo.getActivityId())){
                Task task=activity.getTasks().get(0);
                String formUrl=null;
                switch (formType){
                    case 0:{
                        Form viewForm=((FormTask)task).getViewForm();//只读表单
                        formUrl=viewForm!=null?viewForm.getUri().toString():null;
                        break;
                    }
                    case 1:{
                        Form editForm=((FormTask)task).getEditForm();//编辑表单
                        formUrl=editForm!=null?editForm.getUri().toString():null;
                        break;
                    }
                }
                return formUrl;
            }

        }
        return null;

    }
    /***
     * 根据工作项id查询工作流处理意见
     * @param workItemId
     * @return
     */
    public WorkflowReview queryWorkflowReviewByWorkItemId(String workItemId){
        WorkflowReview workflowReview=null;
        WorkItemInfo workItemInfo=this.queryWorkItemInfoByWorkItemId(workItemId);//查询工作项信息
        //查询工作项处理意见信息
        workflowReview=this.flowManagementMapper.queryWorkflowReviewByWorkItemId(workItemId);
        if (workflowReview==null){
            workflowReview=new WorkflowReview();
        }
        //查询流程定义信息
        WorkflowDefinition workflowDefinition=this.runtimeContext.getPersistenceService().findWorkflowDefinitionByProcessIdAndVersionNumber(workItemInfo.getProcessId(),workItemInfo.getVersion());
        List<Activity> activities=workflowDefinition.getWorkflowProcess().getActivities();
        for (Activity activity:activities){
            if (activity.getId().equals(workItemInfo.getActivityId())){
                Task task=activity.getTasks().get(0);
                Node node=((Synchronizer)activity.getLeavingTransition().getToNode()).getLeavingTransitions().get(0).getToNode();//下一环节
                if (node instanceof Activity){
                    Activity toActivity=(Activity)node;
                    List<Task> tasks=toActivity.getTasks();
                    if (tasks!=null){
                        Task toTask=tasks.get(0);
                        //String isDynamicAssigner=toTask.getExtendedAttributes().get("isDynamicAssigner");
                        //workflowReview.setIsDynamicAssigner("1".equals(isDynamicAssigner)?1:0);
                        workflowReview.setIsDynamicAssigner(1);//是否动态指定人
                        workflowReview.setNextActivityId(toActivity.getId());//下一环节id
                    }
                }
            }

        }
        return workflowReview;
    }
    /***
     * 从request中获取审批意见参数
     * @param request
     * @param requestName
     * @return
     */
    public WorkflowReview getWorkflowReviewByRequest(HttpServletRequest request, String requestName,String workItemId){
        String result=request.getParameter(requestName+".result");//处理结果
        String comments=request.getParameter(requestName+".comments");//处理意见
        String isDynamicAssigner=request.getParameter(requestName+".isDynamicAssigner");//是否动态指定下一环节
        String nextUsers=request.getParameter(requestName+".nextUserId");//下一环节处理人
        String nextActivityId=request.getParameter(requestName+".nextActivityId");//下一环节id
        WorkflowReview workflowReview=new WorkflowReview();
        workflowReview.setResult(result);
        workflowReview.setComments(comments);
        workflowReview.setIsDynamicAssigner(Integer.parseInt(isDynamicAssigner==null?"0":"1"));
        workflowReview.setNextUsers(nextUsers);
        workflowReview.setNextActivityId(nextActivityId);
        workflowReview.setWorkItemId(workItemId);
        return workflowReview;

    }
    /***
     * 保存处理结果
     * @param workflowReview
     * @return
     */
    public boolean saveWorkflowReview(WorkflowReview workflowReview){
        if (workflowReview.getId()==null){
            workflowReview.setId(IDGenerator.getId());
        }
        //保存流程处理意见
        boolean boo=this.flowManagementMapper.saveWorkflowReview(workflowReview);
        //保存下一环节处理人
        if (boo&&workflowReview.getIsDynamicAssigner()==1){
            IWorkItem workItem=this.runtimeContext.getWorkflowSession().findWorkItemById(workflowReview.getWorkItemId());
            IProcessInstance processInstance=this.runtimeContext.getPersistenceService().findProcessInstanceById(workItem.getTaskInstance().getProcessInstanceId());
            processInstance.setProcessInstanceVariable(workflowReview.getNextActivityId(),workflowReview.getNextUsers());
            this.runtimeContext.getPersistenceService().saveOrUpdateProcessInstance(processInstance);
        }
        return boo;
    }
    /***
     * 结束工作项
     * @param workItemId
     */
    public void workItemComplete(String workItemId) throws KernelException {
        IWorkItem workItem=this.runtimeContext.getWorkflowSession().findWorkItemById(workItemId);
        if (workItem.getState()==0){
            workItem.claim();
        }
        WorkflowReview workflowReview=this.queryWorkflowReviewByWorkItemId(workItemId);//获取工作项处理意见
        //驳回或继续
        if (workflowReview!=null&&workflowReview.getResult()!=null&&"0".equals(workflowReview.getResult())){
            //驳回工作流，注意要驳回到流程的上一环节，避免两个环节之间循环驳回
           /* String activityId=workItem.getTaskInstance().getActivityId();
            String processId=workItem.getTaskInstance().getProcessId();
            runtimeContext.getPersistenceService().findTheLatestVersionOfWorkflowDefinitionByProcessId( processId);
*/
            workItem.reject();
        }else{
            workItem.complete();//完成工作项审批
        }

    }
}
